{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "https://www.bilibili.com/video/BV1jt421c7yN/?spm_id_from=333.337.search-card.all.click&vd_source=c6b4f8272ffbef475ad526a4930651ae\n",
    "\n",
    "一、迭代器\n",
    "\n",
    "迭代器是包含__iter__和__next__（魔法方法）的对象\n",
    "    可迭代对象的iter返回一个迭代器；迭代器的iter返回本身\n",
    "    next返回下一个迭代器；直到raise StopIteration"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "python的for循环：\n",
    "1.调用iterables的__iter__获取iterator\n",
    "2.调用iterator的__next__函数，获取下一个值\n",
    "    能获取到就返回下一个值\n",
    "    否则，退出for循环"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "1\n",
      "2\n",
      "3\n",
      "True\n",
      "True\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "mystr = '123'\n",
    "for s in mystr:\n",
    "    print(s)\n",
    "\n",
    "mylst = [1,2,3]\n",
    "for i in mylst:\n",
    "    print(i)\n",
    "\n",
    "myint = 123\n",
    "print(hasattr(mystr, '__iter__'))  # 有__iter__方法的对象，就是iterables（可迭代对象）\n",
    "print(hasattr(mylst, '__iter__'))\n",
    "print(hasattr(myint, '__iter__'))\n",
    "\n",
    "#for n in myint:  # 报错\n",
    "#    print(n)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "# 上面的for循环等价于next(it)：\n",
    "it = iter(mystr) # 等价于 mystr.__iter__()\n",
    "while True:\n",
    "    try:\n",
    "        print(next(it))\n",
    "    except StopIteration:\n",
    "        break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Current memory usage: 0.01705455780029297 MB\n",
      "Peak memory usage: 0.01705455780029297 MB\n",
      "Current memory usage: 0.018749237060546875 MB\n",
      "Peak memory usage: 0.018749237060546875 MB\n"
     ]
    }
   ],
   "source": [
    "# 使用f.readlines()一次读取文件所有行的数据\n",
    "\n",
    "def process_line(line):  # 处理每一行\n",
    "    pass\n",
    "\n",
    "filepath = './logfile.log'\n",
    "\n",
    "import tracemalloc   # 内存查看\n",
    "tracemalloc.start()  # 开始跟踪内存分配\n",
    "\n",
    "with open(filepath,'r') as f:\n",
    "    lines = f.readlines()    # f.readlines(), 这里已经全部加载内存中了\n",
    "\n",
    "current, peak = tracemalloc.get_traced_memory()  # 内存，当前内存和峰值内存使用\n",
    "print(f\"Current memory usage: {current/1024**2} MB\")\n",
    "print(f\"Peak memory usage: {current/1024**2} MB\")\n",
    "\n",
    "for line in lines:\n",
    "    process_line(line)\n",
    "\n",
    "\n",
    "current, peak = tracemalloc.get_traced_memory()  # 内存，当前内存和峰值内存使用\n",
    "print(f\"Current memory usage: {current/1024**2} MB\")\n",
    "print(f\"Peak memory usage: {current/1024**2} MB\")\n",
    "tracemalloc.stop()  # 停止跟踪内存分配\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2024 | connor vill |create21\n",
      "\n",
      "2024 | connor vill |create21\n",
      "\n",
      "2024 | connor vill |create21\n",
      "\n",
      "Current memory usage: 0.14438629150390625 MB\n",
      "Peak memory usage: 0.14438629150390625 MB\n"
     ]
    }
   ],
   "source": [
    "# 定义一个迭代器，内部定义__next__函数，一行行取出log中文件\n",
    "#     __next__函数调用readline()，读取一行\n",
    "\n",
    "class LineIterator:\n",
    "    def __init__(self, filepath):\n",
    "        self.file = open(filepath, 'r')\n",
    "    \n",
    "    def __iter__(self):  # 有iter和next方法的类叫做迭代器类\n",
    "        return self\n",
    "    \n",
    "    def __next__(self):\n",
    "        line = self.file.readline()  # file.readline(), 这里是一行行加载\n",
    "        # if line:  # 仅读取\n",
    "        #     return line\n",
    "        # else:\n",
    "        #     self.file.close()\n",
    "        #     raise StopIteration\n",
    "        while line:\n",
    "            if line.split('|')[2].strip() == 'create21':\n",
    "                return line\n",
    "            line = self.file.readline()\n",
    "        self.file.close()\n",
    "        raise StopIteration\n",
    "\n",
    "import tracemalloc   # 内存查看\n",
    "tracemalloc.start()  # 开始跟踪内存分配\n",
    "\n",
    "line_iter = LineIterator(filepath)\n",
    "for line in line_iter:   # for循环会自动调用__iter__和__next__\n",
    "    print(line)\n",
    "\n",
    "current, peak = tracemalloc.get_traced_memory()  # 内存，当前内存和峰值内存使用\n",
    "print(f\"Current memory usage: {current/1024**2} MB\")\n",
    "print(f\"Peak memory usage: {current/1024**2} MB\")\n",
    "tracemalloc.stop()  # 停止跟踪内存分配\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "二、生成器\n",
    "\n",
    "可以理解为迭代器的简单实现；\n",
    "有2种写法：\n",
    "    1.生成器函数 \n",
    "    2.生成器表达式\n",
    "\n",
    "在yeild处产生一个值，然后退出函数，下次进来时又从yield处继续；"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "before yield\n",
      "0\n",
      "---\n",
      "after yield\n",
      "before yield\n",
      "1\n",
      "after yield\n",
      "before yield\n",
      "2\n",
      "after yield\n"
     ]
    }
   ],
   "source": [
    "def generator(n):\n",
    "    for i in range(n):\n",
    "        print('before yield')\n",
    "        yield i    # 通过yield关键字，生成器会自动产生 next 和iter方法\n",
    "        print('after yield')\n",
    "\n",
    "gen = generator(3)\n",
    "\n",
    "print(next(gen))\n",
    "print('---')\n",
    "\n",
    "for i in gen:\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2024 | connor vill |create21\n",
      "\n",
      "2024 | connor vill |create21\n",
      "\n",
      "2024 | connor vill |create21\n",
      "\n"
     ]
    }
   ],
   "source": [
    "# 生成器函数\n",
    "def line_generator(filepath):\n",
    "    with open(filepath, 'r') as file:\n",
    "        for line in file:\n",
    "            if line.split('|')[2].strip()=='create21':\n",
    "                yield line\n",
    "            else:\n",
    "                continue\n",
    "\n",
    "line_gen = line_generator(filepath)\n",
    "for line in line_gen:\n",
    "    print(line)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "迭代器，和生成器的好处：\n",
    "1.惰性计算，只有在处理这个元素时，才去处理他-->节省内存资源\n",
    "2.生成器没有终点"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "1\n",
      "2\n",
      "3\n",
      "5\n",
      "8\n",
      "13\n",
      "21\n",
      "34\n"
     ]
    }
   ],
   "source": [
    "# 生成器函数例子：斐波那契数列\n",
    "def fib_generate():\n",
    "    cur,nxt = 0,1\n",
    "    while True:\n",
    "        yield cur\n",
    "        cur, nxt = nxt, cur+nxt\n",
    "\n",
    "fib_gen = fib_generate()\n",
    "for _ in range(10):\n",
    "    print(next(fib_gen))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "4\n",
      "6\n",
      "8\n"
     ]
    }
   ],
   "source": [
    "# 生成器函数\n",
    "def multi_generator(x):\n",
    "    num = 1\n",
    "    while True:\n",
    "        res = num*x\n",
    "        yield res\n",
    "        num = num+1\n",
    "\n",
    "multi_gen = multi_generator(2)\n",
    "print(next(multi_gen))\n",
    "print(next(multi_gen))\n",
    "print(next(multi_gen))\n",
    "print(next(multi_gen))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "生成器函数和生成器表达式都是创建Python生成器的方式，但它们有一些关键的不同之处：\n",
    "\n",
    "生成器函数（Generator Function）\n",
    "定义: 使用 yield 语句来返回一系列值的函数被称为生成器函数。\n",
    "特点:\n",
    "    在函数体中可以有一个或多个 yield 语句。\n",
    "    调用生成器函数不会立即执行函数体内的代码；而是返回一个可迭代对象（即生成器对象）。\n",
    "    当生成器的 __next__() 方法被调用时，函数内部的代码从上次停止的位置继续执行，直到找到下一个 yield 语句，然后返回一个值，并再次暂停。\n",
    "    生成器函数可以使用 send() 方法向 yield 表达式传递值。\n",
    "    生成器函数可以拥有复杂的逻辑，并且可以有条件地生成值。\n",
    "\n",
    "生成器表达式（Generator Expression）\n",
    "定义: 类似于列表推导式（list comprehension），但使用圆括号而不是方括号。\n",
    "特点:\n",
    "    更加简洁和紧凑，适合简单的操作。\n",
    "    生成器表达式是在一个表达式的上下文中定义的，通常用于需要一个可迭代对象的地方。\n",
    "    生成器表达式不会占用太多内存，因为它是在需要的时候才生成下一个项。\n",
    "    由于生成器表达式是表达式的一部分，所以不能包含条件分支、循环控制结构等复杂逻辑。\n",
    "    生成器表达式主要用于生成序列，而不是执行复杂的逻辑。\n",
    "\n",
    "示例对比\n",
    "下面是一些生成器函数和生成器表达式的示例，以及如何使用它们："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "4\n",
      "9\n",
      "16\n"
     ]
    }
   ],
   "source": [
    "# 生成器函数\n",
    "\n",
    "def square_numbers(nums):  # 生成器函数\n",
    "    for n in nums:\n",
    "        yield n * n\n",
    "\n",
    "numbers = [1, 2, 3, 4]\n",
    "squares = square_numbers(numbers)\n",
    "for square in squares:\n",
    "    print(square)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "4\n",
      "9\n",
      "16\n"
     ]
    }
   ],
   "source": [
    "# 生成器表达式\n",
    "\n",
    "numbers = [1, 2, 3, 4]\n",
    "squares = (n * n for n in numbers)  # 生成器表达式\n",
    "for square in squares:\n",
    "    print(square)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "schedule",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.19"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
